package mysql

import (
	"WebSvr/modules/common"
	"sync"

	"errors"
	"fmt"

	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	_ "github.com/go-sql-driver/mysql"
)

type DbPcStatus struct {
	Lock sync.RWMutex
}

var gPcStatus *DbPcStatus

func NewPcStatus() {
	gPcStatus = &DbPcStatus{}
}

func GetPcStatus() *DbPcStatus {
	return gPcStatus
}

func (self *DbPcStatus) AnalysePcReport(msgSysReport *common.SysReportInfo) bool {
	cpucount := uint32(len(msgSysReport.CpuUsage))
	memSysCount := uint32(len(msgSysReport.MemSysUsage))
	memProgCount := uint32(len(msgSysReport.MemProgUsage))
	samplecycle := msgSysReport.Samplecycle
	timeStamp := msgSysReport.TimeStamp

	var bsucc bool = true
	var index uint32
	if (cpucount > 0) && (memSysCount > 0) && (memProgCount > 0) {
		for index = 0; index < cpucount; index++ {
			var pcStatus PcStatus
			pcStatus.Name = msgSysReport.ServerName
			pcStatus.TotalMem = msgSysReport.TotalMem
			sliceIndex := cpucount - index - 1
			tmStamp := int64(timeStamp - int64(samplecycle*index))
			tmStr := self.timeStamp2Str(tmStamp)
			pcStatus.Time = tmStr
			pcStatus.CpuUsage = msgSysReport.CpuUsage[sliceIndex]
			pcStatus.MemSysUsage = msgSysReport.MemSysUsage[sliceIndex]
			pcStatus.MemProgUsage = msgSysReport.MemProgUsage[sliceIndex]
			binsert := self.insert2mysql(pcStatus)
			if !binsert {
				bsucc = false
			}
		}
	}

	if bsucc {
		return true
	} else {
		return false
	}

}

func (self *DbPcStatus) timeStamp2Str(timestamp int64) string {
	tm := time.Unix(timestamp, 0)
	strTimeStamp := tm.Format("2006-01-02 15:04:05")
	return strTimeStamp
}

func (self *DbPcStatus) insert2mysql(pcStatus PcStatus) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_DATAREPORT)

	_, errInsert := dbObj.Insert(&pcStatus)
	if errInsert != nil {
		fmt.Println(errInsert)
		dbObj.Rollback()
		beego.Error(errInsert)
		return false
	}
	dbObj.Commit()

	return true
}

func QueryPCDataBySeltype(selType int32, serverName string, table string, xAxiData []string) (cpuData []float64, memData []float64, err error) {
	datalen := len(xAxiData)
	cpuData = make([]float64, 0, datalen)
	memData = make([]float64, 0, datalen)
	switch selType {
	case common.SEL_SEC:
		{
			slice_pcData, errSec := QueryPCDataBySec(serverName, table, xAxiData[0], xAxiData[datalen-1])
			if errSec == nil {
				for _, val := range slice_pcData {
					cpuData = append(cpuData, val.CpuUsage)
					memProgUse := float64(val.MemProgUsage)
					memTotal := float64(val.TotalMem)
					memUsePercent := memProgUse / memTotal * 100
					memData = append(memData, memUsePercent)
				}
				return cpuData, memData, nil
			}

			return cpuData, memData, errSec
		}
	case common.SEL_MIN:
		fallthrough
	case common.SEL_HOUR:
		{
			for index, _ := range xAxiData {
				if index > 0 {
					fmt.Printf("index:%v\n", index)
					pcSub, errSub := QueryPCDataBySec(serverName, table, xAxiData[index-1], xAxiData[index])
					if errSub == nil {
						subLen := len(pcSub)
						if subLen > 0 {
							var cpuSub float64 = 0

							var memUsePercentSub float64 = 0
							fmt.Printf("pcSub[0].TotalMem:%v\n", pcSub[0].TotalMem)
							var memTotalSub uint64 = pcSub[0].TotalMem
							for _, subVal := range pcSub {
								cpuSub += subVal.CpuUsage
								if common.DebugCtrl == 1 {
									memUsePercentSub += float64(subVal.MemSysUsage) / float64(memTotalSub) * 100
								} else {
									memUsePercentSub += float64(subVal.MemProgUsage) / float64(memTotalSub) * 100
								}

							}
							cpuAverage := cpuSub / float64(subLen)
							memUsePercentAverage := memUsePercentSub / float64(subLen)

							cpuData = append(cpuData, cpuAverage)

							memData = append(memData, memUsePercentAverage)
							fmt.Printf("cpuData:%v\n", cpuData)
							fmt.Printf("memData:%v\n", memData)
						} else {
							fmt.Println("not found add zero")
							cpuData = append(cpuData, 0)
							memData = append(memData, 0)
						}

					} else {
						return cpuData, memData, errSub
					}
				} else {
					//index == 0的时候补充第一个点
					pcStart, errStart := queryStartData(serverName, table, xAxiData[0])
					if errStart == nil {
						cpuData = append(cpuData, pcStart.CpuUsage)
						if common.DebugCtrl == 1 {
							memData = append(memData, float64(pcStart.MemSysUsage)/float64(pcStart.TotalMem)*100)
						} else {
							memData = append(memData, float64(pcStart.MemProgUsage)/float64(pcStart.TotalMem)*100)
						}
					} else {
						cpuData = append(cpuData, 0)
						memData = append(memData, 0)
					}
				}
			}

			return cpuData, memData, nil
		}
	default:
		{
			var err error = errors.New("invalid selType")
			return cpuData, memData, err
		}

	}
}

func queryStartData(serverName string, table string, startTime string) (PcStatus, error) {
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_DATAREPORT)

	var pcStartData PcStatus
	var sqlbuf string
	sqlbuf = fmt.Sprintf(
		"select * from `%s` where time = '%s' and name = '%s' order by time;",
		table, startTime, serverName)
	fmt.Printf("queryStartData %s\n", sqlbuf)
	slice_pcInfo := make([]PcStatus, 1)
	_, err := dbObj.Raw(sqlbuf).QueryRows(&slice_pcInfo)
	if err != nil {
		return pcStartData, err
	}
	pcStartData = slice_pcInfo[0]
	return pcStartData, nil

}

func QueryPCDataBySec(serverName string, table string, startTime string, endTime string) ([]PcStatus, error) {
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_DATAREPORT)

	var sqlbuf string
	sqlbuf = fmt.Sprintf(
		"SELECT COUNT(1) FROM `%s` where time between '%s' and '%s' and name = '%s' order by time;",
		table, startTime, endTime, serverName)
	fmt.Printf("mysql cmd:%s\n", sqlbuf)
	slice_count := make([]int, 2)
	_, err := dbObj.Raw(sqlbuf).QueryRows(&slice_count)
	if err != nil {
		return nil, err
	}

	sqlbuf = ""
	slice_pcInfo := make([]PcStatus, slice_count[0])
	sqlbuf = fmt.Sprintf(
		"select * from `%s` where time between '%s' and '%s' and name = '%s' order by time;",
		table, startTime, endTime, serverName)
	fmt.Printf("mysql cmd:%s\n", sqlbuf)
	_, err = dbObj.Raw(sqlbuf).QueryRows(&slice_pcInfo)
	if err != nil {
		return nil, err
	}
	return slice_pcInfo, nil

}
